﻿using EquipmentAlarmSystem.Service.Library;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace EquipmentAlarmSystem.Service.ContentPushUnit;

/// <summary>
/// 短信报警器连接
/// </summary>
public static class SmsAlarmConnection
{
    /// <summary>
    /// 日志记录
    /// </summary>
    static Logging logging = new("SmsAlarmConnection", false);

    /// <summary>
    /// 锁
    /// </summary>
    private static object _lock = new();
    /// <summary>
    /// 服务运行状态标志
    /// </summary>
    private static bool IsRun = false;

    public static bool IsServerRun => IsRun;
    /// <summary>
    /// 服务端口
    /// </summary>
    private static int servicePort = BasicConfiguration.AlarmServicePort;
    /// <summary>
    /// 短信报警器连接对象
    /// </summary>
    private static Socket sockets;
    /// <summary>
    /// 报警器服务对象
    /// </summary>
    private static Socket serverSocket;
    /// <summary>
    /// 时间戳
    /// </summary>
    private static long timestamp = 00001;

    public static long NextHeartbeatTimestamp => timestamp;
    /// <summary>
    /// 报警器状态
    /// </summary>
    public static bool AlarmStatus
    {
        get
        {
            if (IsRun == false) //检查服务状态
            {
                return false;
            }
            else if (sockets is null) //检查连接状态
            {
                return false;
            }
            else if (timestamp < DateTimeOffset.Now.ToUnixTimeSeconds())//时间戳检查
            {
                return false;
            }
            else
            {
                return sockets.Connected;
            }
        }
    }

    public static string AlarmAddress = "";
    /// <summary>
    /// 激活服务
    /// </summary>
    public static void ActivateService()
    {
        //检查服务是否已经在运行
        if (IsRun == false)
        {
            //初始化时间戳
            timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
            //拉起服务端
            new Task(EnableServer).Start();
        }
    }

    /// <summary>
    /// 开启服务端
    /// </summary>
    private static void EnableServer()
    {
        // 创建Socket对象  
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            IsRun = true;
            // 绑定IP地址和端口号   SystemConfiguration.Configuration
            serverSocket.Bind(new IPEndPoint(IPAddress.Parse("0.0.0.0"), servicePort));
            logging.Info($"报警器服务已开启  端口：{servicePort}");  //日志
            // 开始监听  
            serverSocket.Listen(3);
            // 循环接受客户端的连接  
            while (IsRun)
            {
                // 接受客户端连接请求  
                sockets = serverSocket.Accept();
                // 启动一个线程来处理客户端的通信  
                new Task(() => HandleClientCommunication(sockets)).Start();
            }
        }
        catch (Exception ex)
        {
            logging.Info(ex.Message);  //日志
        }
        finally
        {
            // 关闭服务端Socket  
            serverSocket.Close();
            IsRun = false;
            logging.Info("报警器服务已关闭");  //日志
        }
    }

    /// <summary>
    /// 处理客户端通信
    /// </summary>
    /// <param name="clientSocket"></param>
    private static void HandleClientCommunication(Socket clientSocket)
    {
        // 获取远程（客户端）的IPEndPoint信息  
        IPEndPoint clientEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint!;
        AlarmAddress = clientEndPoint.Address.ToString();
        logging.Info($"客户端连接建立;{clientEndPoint.Address}:{clientEndPoint.Port}");  //日志
        // 注册GBK编码  
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        var gbkEncoding = Encoding.GetEncoding("GBK");

        try
        {
            while (clientSocket.Connected)
            {
                // 接收客户端发送的数据（包括心跳包）  
                byte[] buffer = new byte[2048];
                int received = clientSocket.Receive(buffer);
                if (received == 0)
                {
                    // 如果接收到0字节，可能是客户端关闭了连接  
                    logging.Info($"客户端连接已断开;{clientEndPoint.Address}:{clientEndPoint.Port}");  //日志
                    break;
                }
                // 将接收到的字节解码为GBK字符串
                string message = gbkEncoding.GetString(buffer, 0, received);
                ReceiveDataParsing(message);
            }
        }
        catch (Exception ex)
        {
            logging.Info(ex.Message);  //日志
        }
        finally
        {
            // 关闭客户端Socket  
            clientSocket?.Close();
            sockets?.Close();
            sockets = null;
            logging.Info($"客户端连接已断开;{clientEndPoint.Address}:{clientEndPoint.Port}");  //日志
            AlarmAddress = "";
        }
    }

    /// <summary>
    /// 长短信短信内容拼接
    /// </summary>
    private static SortedList<string, string> smsContentSplicing = new();

    /// <summary>
    /// 接收数据解析
    /// </summary>
    private static void ReceiveDataParsing(string content)
    {
        //msg
        if (content.Contains("+CMS"))
        {
            Logging loggings = new("SmsReception");
            //删除包头
            content = content.Replace("+CMS:", "");
            //获取手机号码
            string deletedContent = Regex.Replace(content[..20], @"\s+", "");
            //获取短信内容
            string smsContent = content[20..];
            //协议
            string protocolNumber = Regex.Replace(smsContent.Substring(0, 6), @"\s+", "");
            //删除协议头
            smsContent = smsContent[6..].Replace("\r\n\0\0", "");
            smsContent = Regex.Replace(smsContent.ToString(), @"\s+", "");

            //普通短信解读
            if (protocolNumber == "010101")
            {
                loggings.Info($"time:{Basics.GetDate};form:{deletedContent};msg:{smsContent}\n");
            }
            else
            {
                //长短信解析 msgtemp
                //获取短信标识号
                string identificationNumber = protocolNumber[0..2];
                //获取短信总条数
                string totalNumberOfEntries = protocolNumber[2..4];
                //获取当前条数
                string currentNumberOfEntries = protocolNumber[4..6];

                if (smsContentSplicing.ContainsKey(identificationNumber))
                {
                    if (totalNumberOfEntries == currentNumberOfEntries)
                    {
                        smsContentSplicing[identificationNumber] += smsContent;
                        smsContent = smsContentSplicing[identificationNumber];
                        //独立的日志事件
                        loggings.Info($"time:{Basics.GetDate};form:{deletedContent};msg:{smsContent}");
                        smsContentSplicing.Remove(identificationNumber);
                    }
                    else
                    {
                        smsContentSplicing[identificationNumber] += smsContent;
                    }
                }
                else
                {
                    smsContentSplicing.Add(identificationNumber, smsContent);
                }
            }
        }
        else if (content == Basics.Config.Heartbeat)
        {
            //初始化时间戳
            timestamp = DateTimeOffset.Now.ToUnixTimeSeconds() + 65;
        }
        else
        {
            //非短信内容
            string newString = Regex.Replace(content.ToString(), @"\s+", "").Replace("\n", "");
            //报警器日志数据数据处理
            Logging loggings = new("alarmLog", false);
            loggings.Info($"{Basics.GetDate} {newString}\n");
        }
    }

    /// <summary>
    /// 发送数据
    /// </summary>
    /// <param name="clientSocket"></param>
    /// <param name="message"></param>
    private static void Send(string message)
    {
        lock (_lock)
        {
            try
            {
                if (sockets is null || sockets.Connected == false)
                {
                    return; // 连接已关闭  
                }
                // 注册GBK编码  
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                // 现在你可以使用GBK编码了  
                var gbkEncoding = Encoding.GetEncoding("GBK");
                // 要发送的数据  
                byte[] data = gbkEncoding.GetBytes(message);
                // 发送数据  
                sockets.Send(data);
            }
            catch (Exception ex)
            {
                logging.Info(ex.Message);  //日志
                sockets?.Close();
                sockets = null;
                AlarmAddress = "";
            }
            //发送延迟 1.5S
            Thread.Sleep(1500);
        }
    }

    /// <summary>
    /// 发送短信
    /// </summary>
    /// <param name="phone"></param>
    /// <param name="message"></param>
    public static void SendSms(string phone, string message)
    {
        string strContent = phone + ":0:" + Basics.Config.Autograph + message;
        //2）编码方式：
        //取值‘0’0x30：文本发送，gbk编码格式
        //取值‘1’0x31：二进制数据
        //取值‘3’0x33: tts 语音电话
        //取值‘5’0x35：文本发送 unicde 编码格式 big-endian
        Send(strContent);
    }

    /// <summary>
    /// 拨打电话
    /// </summary>
    /// <param name="phone"></param>
    /// <param name="message"></param>
    public static void SendCall(string phone, string message)
    {
        string strContent = phone + ":3:" + message;
        //2）编码方式：
        //取值‘0’0x30：文本发送，gbk编码格式
        //取值‘1’0x31：二进制数据
        //取值‘3’0x33: tts 语音电话
        //取值‘5’0x35：文本发送 unicde 编码格式 big-endian
        Send(strContent);
    }

    /// <summary>
    /// 服务重启
    /// </summary>
    public static void RestartService()
    {
        logging.Info("报警器连接服务重启");
        EndService();
        ActivateService();
    }

    /// <summary>
    /// 结束服务
    /// </summary>
    public static void EndService()
    {
        sockets?.Close();
        serverSocket?.Close();
        IsRun = false;
        AlarmAddress = "";
    }
}
